/*
* _08LumaQQ - Java _08QQ Client
*
* Copyright (C) 2004 luma <stubma@163.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package edu.tsinghua.lumaqq.qq;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import edu.tsinghua.lumaqq.qq.events.IPacketListener;
import edu.tsinghua.lumaqq.qq.events.PacketEvent;
import edu.tsinghua.lumaqq.qq.events._08QQEvent;
import edu.tsinghua.lumaqq.qq.packets.ErrorPacket;
import edu.tsinghua.lumaqq.qq.packets._08InPacket;
import edu.tsinghua.lumaqq.qq.packets._08OutPacket;
import edu.tsinghua.lumaqq.qq.packets._05InPacket;
import edu.tsinghua.lumaqq.qq.packets.in._05.RequestAgentReplyPacket;
import edu.tsinghua.lumaqq.qq.packets.in._05.Unknown05InPacket;

/**
 * 05系列包处理器
 *
 * @author luma
 */
class _05FamilyProcessor implements IPacketListener {
    // Log对象
    static Log log = LogFactory.getLog(_05FamilyProcessor.class);

    // QQ客户端
    private _08QQClient client;

    public _05FamilyProcessor(_08QQClient client) {
        this.client = client;
    }

    /* (non-Javadoc)
    * @see edu.tsinghua.lumaqq.qq.events.IPacketListener#packetArrived(edu.tsinghua.lumaqq.qq.events.PacketEvent)
    */
    public void packetArrived(PacketEvent e) {
        if (e.getSource() instanceof ErrorPacket) {
            processError((ErrorPacket) e.getSource());
            return;
        }

        _05InPacket in = (_05InPacket) e.getSource();
        if (in instanceof Unknown05InPacket) {
            log.debug("收到一个未知格式包");
            return;
        }

        // 清楚重发包
        client.removeResendPacket(in);
        log.debug("包" + (int) in.getSequence() + "的确认已经收到，将不再发送");

        // 判断包命令，处理
        switch (in.getCommand()) {
            case _08QQ.QQ_05_CMD_REQUEST_AGENT:
                processRequestAgentReply(in);
                break;
            case _08QQ.QQ_05_CMD_REQUEST_FACE:
                processRequestFaceReply(in);
                break;
            case _08QQ.QQ_05_CMD_REQUEST_BEGIN:
                processRequestBeginReply(in);
                break;
            case _08QQ.QQ_05_CMD_TRANSFER:
                processTransferReply(in);
                break;
        }
    }

    /**
     * 处理错误事件
     *
     * @param packet
     */
    private void processError(ErrorPacket error) {
        _08QQEvent e = null;
        switch (error.errorCode) {
            case ErrorPacket.ERROR_TIMEOUT:
                _08OutPacket packet = error.timeoutPacket;
                e = new _08QQEvent(packet);
                e.type = _08QQEvent.SYS_TIMEOUT_05;
                e.operation = packet.getCommand();
                break;
            case ErrorPacket.ERROR_PROXY:
                e = new _08QQEvent(error);
                e.type = _08QQEvent.ERROR_PROXY;
                break;
            case ErrorPacket.ERROR_NETWORK:
                e = new _08QQEvent(error);
                e.type = _08QQEvent.ERROR_NETWORK;
                break;
        }

        if (e != null)
            client.fireQQEvent(e);
    }

    /**
     * 处理请求自定义表情回复包
     *
     * @param in
     */
    private void processRequestFaceReply(_05InPacket in) {
        _08QQEvent e;

        e = new _08QQEvent(in);
        e.type = _08QQEvent.FILE_REQUEST_FACE_OK;
        client.fireQQEvent(e);
    }

    /**
     * 处理传送回复包
     *
     * @param in
     */
    private void processTransferReply(_05InPacket in) {
        _08QQEvent e;

        if (in.getSource() == _08QQ.QQ_CLIENT_VERSION) {
            e = new _08QQEvent(in);
            e.type = _08QQEvent.FILE_TRANSFER_FACE_OK;
            client.fireQQEvent(e);
        } else {
            if (in.getSequence() == 0) {
                e = new _08QQEvent(in);
                e.type = _08QQEvent.FILE_FACE_INFO_RECEIVED;
                client.fireQQEvent(e);
            } else {
                e = new _08QQEvent(in);
                e.type = _08QQEvent.FILE_FACE_DATA_RECEIVED;
                client.fireQQEvent(e);
            }
        }
    }

    /**
     * 处理请求开始回复包
     *
     * @param in
     */
    private void processRequestBeginReply(_05InPacket in) {
        _08QQEvent e;

        log.debug("服务器同意开始发送");
        e = new _08QQEvent(in);
        e.type = _08QQEvent.FILE_REQUEST_BEGIN_OK;
        client.fireQQEvent(e);
    }

    /**
     * 处理请求中转服务器请求包
     *
     * @param in
     */
    private void processRequestAgentReply(_05InPacket in) {
        _08QQEvent e;
        RequestAgentReplyPacket packet = (RequestAgentReplyPacket) in;

        switch (packet.replyCode) {
            case _08QQ.QQ_REPLY_REQUEST_AGENT_REDIRECT:
                log.debug("请求中转服务器重定向， to " + Util.convertIpToString(packet.redirectIp));
                e = new _08QQEvent(packet);
                e.type = _08QQEvent.FILE_REQUEST_AGENT_REDIRECT;
                client.fireQQEvent(e);
                break;
            case _08QQ.QQ_REPLY_REQUEST_AGENT_OK:
                log.debug("请求中转服务器成功");
                e = new _08QQEvent(packet);
                e.type = _08QQEvent.FILE_REQUEST_AGENT_OK;
                client.fireQQEvent(e);
                break;
            case _08QQ.QQ_REPLY_REQUEST_AGENT_TOO_LONG:
                log.debug(packet.message);
                e = new _08QQEvent(packet);
                e.type = _08QQEvent.FILE_REQUEST_AGENT_FAIL;
                client.fireQQEvent(e);
                break;
            default:
                log.debug("未知的Request Agent回复码: " + (int) packet.replyCode);
                break;
        }
    }

    /* (non-Javadoc)
      * @see edu.tsinghua.lumaqq.qq.events.IPacketListener#accept(edu.tsinghua.lumaqq.qq.packets._08InPacket)
      */
    public boolean accept(_08InPacket in) {
        return (in.getFamily() & _08QQ.QQ_PROTOCOL_FAMILY_05) != 0;
	}
}
